package wordnet;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import net.didion.jwnl.JWNL;
import net.didion.jwnl.JWNLException;
import net.didion.jwnl.data.IndexWord;
import net.didion.jwnl.data.IndexWordSet;
import net.didion.jwnl.data.Pointer;
import net.didion.jwnl.data.PointerType;
import net.didion.jwnl.data.Synset;
import net.didion.jwnl.data.Word;
import net.didion.jwnl.dictionary.Dictionary;
import utility.cache.LRUCache;

public class NaiveWordnetOperator implements IWordnetOperator {
	

	private LRUCache<String, String> _cacheStringToString;
	private Dictionary _dictionary;
	private LRUCache<String, List<String>> _cacheStringToList;

	public NaiveWordnetOperator(){
		try {
			JWNL.initialize(new FileInputStream("./config/file_properties.xml"));
			_dictionary = Dictionary.getInstance();
			_cacheStringToString = new LRUCache<String, String>(10000);
			_cacheStringToList = new LRUCache<String, List<String>>(10000);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (JWNLException e) {
			e.printStackTrace();
		}
	}
	
	public String makeSubstitutionFor(String aWord){
		String result = aWord;
		String inCache = _cacheStringToString.get(aWord);
		if (inCache!=null) return inCache;
		try {
			Set<String> allSenses = new HashSet<String>();
			IndexWordSet indexWordSet = _dictionary.lookupAllIndexWords(aWord);
			IndexWord[] word = indexWordSet.getIndexWordArray();
			for (IndexWord eachWord : word) {
				Synset[] senses = eachWord.getSenses();
				for (Synset eachSense : senses) {
					allSenses.add(eachSense.getLexFileName());
				}
			}
			if (allSenses.size()>0&&allSenses.size()<4) result =(String)allSenses.toArray()[0];
		} catch (JWNLException e) {
			e.printStackTrace();
		}
		
		_cacheStringToString.put(aWord, result);
		return result;
	}

	private void putAnHypernymOfIn(String aWord, List<String> wordList) {
		if(_cacheStringToList.get(aWord)!=null){
			wordList.addAll(_cacheStringToList.get(aWord));
			return;
		}
		
		
		Set<String> result = new HashSet<String>();
		try {
			IndexWordSet indexWordSet = _dictionary.lookupAllIndexWords(aWord);
			IndexWord[] word = indexWordSet.getIndexWordArray();
			for (IndexWord eachWord : word) {
				Synset[] senses = eachWord.getSenses();
				for (Synset eachSense : senses) {
//					allSenses.add(eachSense.getLexFileName());
					Pointer[] pointers = eachSense.getPointers(PointerType.HYPERNYM);
					for (Pointer pointer : pointers) {
						Synset target = pointer.getTargetSynset();
						Word[] words = target.getWords();
						if(words.length>0) result.add(words[0].getLemma());
					}
				}
			}
		} catch (JWNLException e) {
			e.printStackTrace();
		}
		wordList.addAll(result);
		ArrayList<String> listInCache = new ArrayList<String>();
		listInCache.addAll(result);
		_cacheStringToList.put(aWord, listInCache);
	}
	
	public String hypernymFor(String aWord) {
		
		String hypernym = _cacheStringToString.get(aWord);
		if(hypernym!=null) return hypernym;
		
		hypernym = aWord;				
		try {
			IndexWordSet indexWordSet = _dictionary.lookupAllIndexWords(aWord);
			IndexWord[] word = indexWordSet.getIndexWordArray();
			for (IndexWord eachWord : word) {
				Synset[] senses = eachWord.getSenses();
				for (Synset eachSense : senses) {
					Pointer[] pointers = eachSense.getPointers(PointerType.HYPERNYM);
					for (Pointer pointer : pointers) {
						Synset target = pointer.getTargetSynset();
						Word[] words = target.getWords();
						if(words.length>0) hypernym = words[0].getLemma();
					}
				}
			}
		} catch (JWNLException e) {
			e.printStackTrace();
		}
		_cacheStringToString.put(aWord, hypernym);
		return hypernym;
	}

	public void makeSubstitutionFor(List<String> words) {
		List<String> copyOfWords = new ArrayList<String>();
		copyOfWords.addAll(words);
		for (String each : copyOfWords) {
			String substitution = makeSubstitutionFor(each);
			int eachIndex = words.indexOf(each);
			if(!substitution.equals(each)){
				words.remove(each);
				words.add(eachIndex, substitution);				
			}
		}
	}

	public void makeSubstitutionWithHypernymsIn(List<String> words) {
		List<String> result = new ArrayList<String>();
		for (String each : words) {
			result.add(hypernymFor(each));
		}
		words.clear();
		words.addAll(result);
	}

	public void expandsWithHypernyms(List<String> words) {
		List<String> result = new ArrayList<String>();
		for(int i=0;i<words.size();i++){
			putAnHypernymOfIn(words.get(i),result);
		}
		words.addAll(result);
	}

}
